package com.foamya.minego

import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import kotlin.streams.toList

class RecyclerAdapter(private var context: Context) :
    RecyclerView.Adapter<RecyclerAdapter.Holder>() {

    private lateinit var onBehaviorListener: OnBehaviorListener

    fun setOnEnsureListener(onBehaviorListener: OnBehaviorListener) {
        this.onBehaviorListener = onBehaviorListener
    }

    interface OnBehaviorListener {
        fun gameStart() // 开始游戏

        fun useShovel(x: Int, y: Int) // 使用铲子

        fun useFlag() // 使用旗子

        fun cancelFlag() // 取消旗子

        fun gameWin() // 游戏获胜

        fun gameFail() // 游戏失败
    }

    class Holder(view: View) : RecyclerView.ViewHolder(view) {
        val boxTv: TextView = view.findViewById(R.id.item_box_rv_tv)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        return Holder(LayoutInflater.from(context).inflate(R.layout.item_box, parent, false))
    }

    override fun getItemCount(): Int {
        return BoxUtil.rowSpan * BoxUtil.colSpan
    }

    @SuppressLint("NotifyDataSetChanged")
    override fun onBindViewHolder(holder: Holder, position: Int) {

        // 根据每行的数量获取x,y坐标
        val x = position / BoxUtil.rowSpan // 当前位置x坐标
        val y = position - BoxUtil.rowSpan * x // 当前位置y坐标

        val expandMap = BoxUtil.isExpandMap
        val boxMark = BoxUtil.boxMarkArr[x][y]
        val boxNum = BoxUtil.boxNumArr[x][y]

        when (boxMark) {
            0 -> {
                holder.boxTv.text = ""
                holder.boxTv.setBackgroundResource(
                    if (expandMap && BoxUtil.shovelFailPos == position)
                        R.mipmap.box_trap_open_error
                    else if (expandMap && boxNum == -1)
                        R.mipmap.box_trap_open
                    else R.mipmap.box_empty
                )
            }

            1 -> {
                holder.boxTv.text = // 设置文字
                    if (boxNum == 0) ""
                    else boxNum.toString()
                holder.boxTv.setTextColor( // 给不同数字不同文字颜色
                    when (boxNum) {
                        1 -> ContextCompat.getColor(context, R.color.box_1)
                        2 -> ContextCompat.getColor(context, R.color.box_2)
                        3 -> ContextCompat.getColor(context, R.color.box_3)
                        4 -> ContextCompat.getColor(context, R.color.box_4)
                        5 -> ContextCompat.getColor(context, R.color.box_5)
                        6 -> ContextCompat.getColor(context, R.color.box_6)
                        7 -> ContextCompat.getColor(context, R.color.box_7)
                        else -> ContextCompat.getColor(context, R.color.box_8)
                    }
                )
                holder.boxTv.setBackgroundResource(R.drawable.box_rectangle_empty_frame)
            }

            2 -> {
                holder.boxTv.text = ""
                holder.boxTv.setBackgroundResource(
                    if (expandMap && boxNum != -1)
                        R.mipmap.box_flag_error
                    else R.mipmap.box_flag
                )
            }
        }

        holder.boxTv.setOnClickListener {// 监听点击
            when (boxMark) { // 根据当前方块的标记判断行为
                0 -> { // 当标记为未翻开
                    // 根据游戏方式判断行为
                    if (BoxUtil.isFlag) // 使用旗子进行游戏时
                        useFlagMethod(position) // 使用旗子
                    else  // 使用铲子子进行游戏时
                        if (useShovelMethod(position)) // 使用铲子
                            return@setOnClickListener
                }

                1 -> { // 当标记为翻开
                    if (openClickMethod(position)) // 点击已翻开
                        return@setOnClickListener
                }

                2 -> { // 当标记为旗子
                    cancelFlagMethod(position) // 取消标旗
                }
            }
            notifyDataSetChanged() // 刷新页面
            if (BoxUtil.lastNotMineNum == 0) { // 如果剩余的非雷方块数量为0
                onBehaviorListener.gameWin() // 游戏胜利
            }
            return@setOnClickListener
        }

        holder.boxTv.setOnLongClickListener {// 监听长按
            when (boxMark) { // 根据当前方块的标记判断行为
                0 -> { // 当标记为未翻开
                    // 根据游戏方式判断行为
                    if (!BoxUtil.isFlag) // 使用铲子进行游戏时
                        useFlagMethod(position) // 使用旗子
                    else  // 使用旗子子进行游戏时
                        if (useShovelMethod(position)) // 使用铲子
                            return@setOnLongClickListener true
                }

                1 -> { // 当标记为翻开
                    if (openClickMethod(position)) // 点击已翻开
                        return@setOnLongClickListener true
                }

                2 -> { // 当标记为旗子
                    cancelFlagMethod(position) // 取消标旗
                }
            }
            notifyDataSetChanged() // 刷新页面
            if (BoxUtil.lastNotMineNum == 0) { // 如果剩余的非雷方块数量为0
                onBehaviorListener.gameWin() // 游戏胜利
            }
            return@setOnLongClickListener true
        }
    }

    /**
     * 点击已翻开方法
     */
    @SuppressLint("NotifyDataSetChanged")
    private fun openClickMethod(position: Int): Boolean {

        // 根据每行的数量获取x,y坐标
        val x = position / BoxUtil.rowSpan // 当前位置x坐标
        val y = position - BoxUtil.rowSpan * x // 当前位置y坐标

        val aroundBoxList = BoxUtil.getAroundBoxInfo(x, y) // 获取当前位置周围一圈的方块信息
        val flagBoxList = aroundBoxList.stream().filter { it[3] == 2 }.toList() // 筛选标记为旗子的方块
        val emptyList = aroundBoxList.stream().filter { it[3] == 0 }.toList() // 筛选标记为未翻开的方块

        if (flagBoxList.size == BoxUtil.boxNumArr[x][y]) { // 当标记为旗子的数量与当前位置数值相同
            for (i in emptyList) { // 便利将未翻开的位置翻开

                if (BoxUtil.boxNumArr[i[0]][i[1]] == -1) { // 如果当前方块的数值为雷
                    BoxUtil.shovelFailPos = position // 记录点击失败的位置
                    BoxUtil.isExpandMap = true // 展开地图
                    notifyDataSetChanged() // 刷新地图
                    onBehaviorListener.gameFail() // 游戏失败
                    return true
                }

                onBehaviorListener.useShovel(i[0], i[1]) // 使用铲子
            }

        } else if (flagBoxList.size + emptyList.size == BoxUtil.boxNumArr[x][y]) {
            // 当标记为旗子的数量和标记为未翻开的数量之和与当前位置数值相同
            for (i in emptyList) { // 便利将未翻开的位置标旗

                BoxUtil.boxMarkArr[i[0]][i[1]] = 2 // 标记当前位置为旗子
                onBehaviorListener.useFlag() // 使用旗子
                if (BoxUtil.boxNumArr[i[0]][i[1]] != -1) { // 如果当前方块不是雷
                    BoxUtil.flagWrongPosList.add(position) // 记录当前错误标记的位置
                }
            }

        } else { // 其他不进行操作
            return true
        }
        return false
    }

    /**
     * 使用铲子方法
     */
    @SuppressLint("NotifyDataSetChanged")
    private fun useShovelMethod(position: Int): Boolean {

        // 根据每行的数量获取x,y坐标
        val x = position / BoxUtil.rowSpan // 当前位置x坐标
        val y = position - BoxUtil.rowSpan * x // 当前位置y坐标

        if (!BoxUtil.isCreateMine) { // 没有创建雷区
            onBehaviorListener.gameStart() // 开始游戏
            BoxUtil.createMine(x, y) // 使用当前位置创建雷区
        }

        if (BoxUtil.boxNumArr[x][y] == -1) { // 如果当前方块的数值为雷
            BoxUtil.shovelFailPos = position // 记录点击失败的位置
            BoxUtil.isExpandMap = true // 展开地图
            notifyDataSetChanged() // 刷新地图
            onBehaviorListener.gameFail() // 游戏失败
            return true
        }

        onBehaviorListener.useShovel(x, y) // 使用铲子
        return false
    }

    /**
     * 标旗方法
     */
    private fun useFlagMethod(position: Int) {

        // 根据每行的数量获取x,y坐标
        val x = position / BoxUtil.rowSpan // 当前位置x坐标
        val y = position - BoxUtil.rowSpan * x // 当前位置y坐标

        if (!BoxUtil.isCreateMine) { // 没有创建雷区
            onBehaviorListener.gameStart() // 开始游戏
            BoxUtil.createMine(x, y) // 使用当前位置创建雷区
        }

        BoxUtil.boxMarkArr[x][y] = 2 // 标记当前位置为旗子
        onBehaviorListener.useFlag() // 使用旗子
        if (BoxUtil.boxNumArr[x][y] != -1) { // 如果当前方块不是雷
            BoxUtil.flagWrongPosList.add(position) // 记录当前错误标记的位置
        }
    }

    /**
     * 取消标旗方法
     */
    private fun cancelFlagMethod(position: Int) {

        // 根据每行的数量获取x,y坐标
        val x = position / BoxUtil.rowSpan // 当前位置x坐标
        val y = position - BoxUtil.rowSpan * x // 当前位置y坐标

        BoxUtil.boxMarkArr[x][y] = 0 // 标记当前位置为未翻开
        onBehaviorListener.cancelFlag() // 取消标旗
        if (BoxUtil.boxNumArr[x][y] != -1) { // 如果当前方块不是雷
            BoxUtil.flagWrongPosList.remove(position) // 移除当前错误标记的位置
        }
    }

}